# Copyright (c) 2008-2009 Mikhail Chernov 
#
# This file is part of dcExplorer.
#
# dcExplorer is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# dcExplorer is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with dcExplorer.  If not, see <http://www.gnu.org/licenses/>.

# Scripting class with extensions
package dcExplorer::core::Fleets;
use strict;
use utf8;
use WeakRef;
use core::Fleet;
use server::Command;

# Construction methods

sub new 
{
	my $proto = shift;
	my $class = ref($proto) || $proto;
	my $self = {};
	weaken($self->{Parent} = shift);
	$self->{Fleets} = ();
	$self->{ByPlanets} = {};
	$self->{ById} = {};
	bless ($self, $class);
	return $self;
}

sub set
{
	my $self = shift;
	my $fleet = shift;
	my $coord = sprintf("%04d:%04d", $fleet->getProp("x"), $fleet->getProp("y"));
	push @{$self->{Fleets}}, $fleet;
	push @{$self->{ByPlanets}->{$coord}}, $fleet;
	$self->{ById}->{$fleet->getProp('id')} = $fleet if defined $fleet->getProp('id'); 
}

# Internal engine methods

sub getEmpire
{
	my $self = shift;
	return $self->{Parent}->getEmpire();
}

# Scripting interface

sub getFleetByID
{
	my $self = shift;
	my $fleetId = shift;
	return $self->{ById}->{$fleetId};
}

sub getFleetsByName
{
	my $self = shift;
	my $name = shift;
	$name =~ s/%/.*/g;
	$name =~ s/_/./g;
	my @res;
	for my $fleet (@{$self->{Fleets}})
	{
		push @res, $fleet if $fleet->getProp('name') =~ /^$name$/;
	}
	return @res;
}

sub getFleetsByLocation
{
	my $self = shift;
	my $x = shift;
	my $y = shift;
	my $coord = sprintf("%04d:%04d", $x, $y);
	return defined($self->{ByPlanets}->{$coord}) ? @{$self->{ByPlanets}->{$coord}} : ();
}

# Actions support

sub __moveFleet
{
	my $self = shift;
	my $fleet = shift;
	my ($from_x, $from_y, $x, $y) = @_;
	my $coord = sprintf('%04d:%04d', $from_x, $from_y);
	@{$self->{ByPlanets}->{$coord}} = grep {$_->getProp('id') != $fleet->getProp('id')} @{$self->{ByPlanets}->{$coord}};
	$coord = sprintf('%04d:%04d', $x, $y);
	push @{$self->{ByPlanets}->{$coord}}, $fleet;
}

sub HideAction
{
	my $self = shift;
	my $fleet = shift;
	my $mode = shift;
	$self->getEmpire()->setProp('money', $self->getEmpire()->getProp('money') - $fleet->getHideCost) if $mode eq 'hide_fleet';
	$self->getEmpire()->setProp('money', $self->getEmpire()->getProp('money') + $fleet->getHideCost) if $mode eq 'cancelhide_fleet';
	$self->getEmpire()->commandQueue()->enqueue(dcExplorer::server::Command->new('hidefleet', {'fleet_id' => $fleet->getProp('id'), 'mode' => $mode}));
}

sub Move
{
	my $self = shift;
	my $fleet = shift;
	my ($x, $y, $t) = @_;
	return undef unless $self->{Parent}->planets->get($x, $y)->getProp('jumpable') || $self->{Parent}->planets->get($fleet->getProp('x'), $fleet->getProp('y'))->getProp('jumpable');
	$fleet->setProp('from_x', $fleet->getProp('x'));
	$fleet->setProp('from_y', $fleet->getProp('y'));
	$fleet->setProp('x', $x);
	$fleet->setProp('y', $y);
	$fleet->setProp('turns_till_arrival', $t); 
	$self->__moveFleet($fleet, $fleet->getProp('from_x'), $fleet->getProp('from_y'), $fleet->getProp('x'), $fleet->getProp('y'));
	$self->getEmpire()->commandQueue()->enqueue(dcExplorer::server::Command->new('move_fleet', {'fleet_id' => $fleet->getProp('id'), 'move_to' => $x.':'.$y}));
	return 1;
}

sub CancelMove
{
	my $self = shift;
	my $fleet = shift;
	$self->__moveFleet($fleet, $fleet->getProp('x'), $fleet->getProp('y'), $fleet->getProp('from_x'), $fleet->getProp('from_y'));
	$fleet->setProp('x', $fleet->getProp('from_x'));
	$fleet->setProp('y', $fleet->getProp('from_y'));
	$fleet->setProp('turns_till_arrival', 0);
	$self->getEmpire()->commandQueue()->enqueue(dcExplorer::server::Command->new('cancel_jump', {'fleet_id' => $fleet->getProp('id')}, sub{}));
	return 1;
}

sub RenameFleet
{
	my $self = shift;
	my $fleet = shift;
	$self->getEmpire()->commandQueue()->enqueue(dcExplorer::server::Command->new('change_fleet_name', {'fleet_id' => $fleet->getProp('id'), 'name' => $fleet->getProp('name'), 'public_name' => $fleet->getProp('ext_name')}));
	return 1;
}

sub SetFleetBehaviour
{
	my $self = shift;
	my $fleet = shift;
	my $params = {'fleet_id' => $fleet->getProp('id')};
	my $behaviour = $fleet->getProp('behaviour');
	for (my $i = 0; $i < 6; ++$i)
	{
		$params->{'behavtrgt_'.($i - 1)} = substr($behaviour, $i, 1);
	}
	$self->getEmpire()->commandQueue()->enqueue(dcExplorer::server::Command->new('change_behaviour', $params)); 
	return 1;
}

1;
